<?php
/**
 * This file is part of workerman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link http://www.workerman.net/
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */

namespace app\worker;
/**
 * 推送主逻辑
 * 主要是处理 onMessage onClose
 */


use GatewayWorker\Lib\Gateway;
use app\worker\Application;
use think\Exception;
use think\facade\Config;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use thans\jwt\provider\JWT\Lcobucci;
use think\facade\Db;
use utils\Aes;

class Events
{

    protected static $user_id = 1;

    public static function execute()
    {
        try {
            $time = time();
            $userList =  Db::name('user')->where('id', '>=', static::$user_id)->where('group_id', 1)
                ->where('level', '<', 4)
                ->field('id,pid,nickname,email,level,bio,verification,gender,updatetime,expire_time')->select();
            foreach ($userList as $key => $val) {
                static::$user_id = $val['id'];
                
                $expire_time = empty($val['expire_time']) ? 0 : strtotime($val['expire_time']);
                if ($time > $expire_time) {
                    Db::name('user')->where('id', $val['id'])->update([
                        'expire_time' => null,
                        'level' => 1,
                        'updatetime' => $time,
                    ]);
                }
            }
//            print "****************设置已读成功******************\n";
        } catch (Exception $e) {
//            print '设置已读失败:' . $e->getMessage() . "\n";
        }
    }


    // 使用TP框架
    public static function onWorkerStart($worker)
    {
        $app = new Application;
        $app->initialize();
        \Workerman\Timer::add(15, function () use ($worker) {
            $onlineUserList = \GatewayClient\Gateway::getAllUidList();
//            dump('在线会员：', $onlineUserList);
            $userList = Db::name('user')->where(['verification' => 'normal', 'online_status' => 1])->field('id,email,verification')->limit(20)->select();
            if (!empty($userList)) {
                foreach ($userList as $key => $value) {
                    $user_id = $value['id'];
                    if (!in_array($value['id'], $onlineUserList)) {
                        $user_default = Db::name('user')->where('id', $user_id)->value('online_status');
                        if ($user_default == 1) {
                            Db::name('user')->where('id', $user_id)->update(['verification' => 'hidden', 'updatetime' => time()]);
                        }
                    }
                }
            }
            
            self::execute();
        });
        
    }

    // 当有客户端连接时，将client_id返回，让mvc框架判断当前uid并执行绑定
    public static function onConnect($client_id)
    {
        Gateway::sendToClient($client_id, json_encode(array(
            'type' => 'init',
            'client_id' => $client_id
        )));
    }

    /**
     * 有消息时
     * @param int $client_id
     * @param mixed $message
     */
    public static function onMessage($client_id, $message)
    {
        // 客户端传递的是json数据
        $message_data = json_decode($message, true);
        if (!$message_data) {
            return;
        }
        // dump('在线会员：', $message_data);
 
        if (isset($message_data['type'])) {
            // 根据类型执行不同的业务
            switch ($message_data['type']) {
                // 客户端回应服务端的心跳
                case 'pong':
                    break;
                case 'ping':
                   
                    self::sendStatus($client_id);
                    break;
                case 'bindUid':
                    self::auth($client_id, $message_data);
                    break;
                case 'online':
                    if(isset($message_data['user_id'])){
                        $user_default = Db::name('user')->where('id', $message_data['user_id'])->value('online_status');
                        if ($user_default == 1) {
                            Db::name('user')->where('id', $message_data['user_id'])->update(['verification' => 'normal', 'updatetime' => time()]);
                        }
                    }
                    break;
                case 'is_read':
                    wsSendMsg($message_data['to_user'], 'is_read', ['user_id' => $message_data['user_id'], 'to_user' => $message_data['to_user'], 'is_read' => 0]);
                    break;
            }
        }
        return;
    }

    protected static function sendStatus($client_id)
    {
        $uid = $_SESSION['user_id'] ?? 0;
        $multiport = false;
        if ($uid) {
            $arr = Gateway::getClientIdByUid($uid);
            if (count($arr) > 1) {
                $multiport = true;
                $user_default = Db::name('user')->where('id', $uid)->value('online_status');
                if ($user_default == 1) {
                    Db::name('user')->where('id', $uid)->update(['verification' => 'normal', 'updatetime' => time()]);
                }                
            }
        }
        Gateway::sendToClient($client_id, json_encode(array(
            'type' => 'pong',
            'multiport' => $multiport,
        )));
    }

    //验证用户的真实性并绑定
    protected static function auth($client_id, $msg)
    {
        $token = $msg['token'] ?? '';
        $config = Config::get('jwt');
        $keys = $config['secret'] ?: [
            'public' => $config['public_key'],
            'private' => $config['private_key'],
            'password' => $config['password'],
        ];
        $provider = new Lcobucci(new Builder(), new Parser(), $config['algo'], $keys);
        try {
            $token = str_replace('bearer ', '', $token);
            $jwtData = $provider->decode((string)$token);
        } catch (\Exception $exception) {
            self::closeClient($client_id);
        }

        $userInfo = $jwtData['info']->getValue();
        //解密token中的用户信息
        $userInfo = Aes::decrypt($userInfo, config('app.aes_token_key'));
        //解析json
        $userInfo = (array)json_decode($userInfo, true);
        if (!$userInfo) {
            self::closeClient($client_id);
        }
        $_SESSION['user_id'] = $userInfo['user_id'];
        self::sendStatus($client_id);
    }

    //断开连接
    protected static function closeClient($client_id)
    {
        $_SESSION['user_id'] = null;
        Gateway::closeClient($client_id);
    }

    /**
     * 当断开连接时
     * @param int $client_id
     */
    public static function onClose($client_id)
    {
        if (isset($_SESSION['user_id'])) {
            $user_id = $_SESSION['user_id'];
            if ($user_id) {
                Gateway::sendToAll(json_encode(array(
                    'type' => 'isOnline',
                    'time' => time(),
                    'data' => ['id' => $user_id, 'is_online' => 0]
                )));

                $user_default = Db::name('user')->where('id', $user_id)->value('online_status');
                if ($user_default == 1) {
                    Db::name('user')->where('id', $user_id)->update(['verification' => 'hidden', 'updatetime' => time()]);
                }

            }
        }
    }

}
